﻿using System.Collections;
using System.Collections.Generic;
using System;
using UnityEngine;
using UnityEngine.UI;

public class UIGameObject{
    public GameObject obj { get; set; }
    public string assetBundleName;
    public string assetName;
    public UIGameObject(GameObject obj, string assetBundleName,string assetName)
    {
        this.obj = obj;
        this.assetBundleName = assetBundleName;
        this.assetName = assetName;
    }

    public void Dispose() {
        GameObject.Destroy(obj);
        obj = null;
        //通知垃圾回收机制不再调用终结器（析构器）
        //GC.SuppressFinalize(this);
    }
}

/// <summary>
/// TODO:应该移到热更脚本里去，因为本身是ui模块的管理类，而ui模块是热更脚本里的功能模块，移过去后需要改造资源加载流程
/// </summary>
public class UIManager : BaseManager {
    public enum DestroyType
    {
        NEVER_DESTROY=0,
        IMMEDIATE_DESTROY=1,
        DELAY_DESTROY=2,
    }
    public enum DisplayLevel
    {
        none = 0,
        /// <summary>
        /// 模块功能UI
        /// </summary>
        mainview = 1,
        /// <summary>
        /// 虚拟摇杆操作界面
        /// </summary>
        joystick = 2,
        /// <summary>
        /// 提示框
        /// </summary>
        confirm = 3,
        /// <summary>
        /// loading层
        /// </summary>
        loading = 4,
        /// <summary>
        /// 最高层tips
        /// </summary>
        tips = 5,
    };

    public const string Param_Prarent = "parent";
    public const string Param_AssetBundleName = "assetBundleName";
    public const string Param_AssetName = "assetName";
    public const string Param_DisplayLv = "displayLv";
    public const string Param_DestroyType = "destroyType";

    public Vector2 UI_PIVOT_CENTER = new Vector2(0.5f, 0.5f);
    /// <summary>
    /// key:abname_assetName,value:UIGameObject
    /// </summary>
    Dictionary<string, UIGameObject> uiLists = new Dictionary<string, UIGameObject>();

    public Dictionary<DisplayLevel, int> displayLevelSortOrder = new Dictionary<DisplayLevel, int>();

    public SortedDictionary<int, GameObject> uiHierarchyLists = new SortedDictionary<int, GameObject>();

    public Camera uiCamera;
    private GameObject m_mainCanvas;
    public GameObject mainCanvas {
        get {
            if (m_mainCanvas == null) {
                m_mainCanvas = GameObject.Find("MainCanvas");
            }
            return m_mainCanvas;
        }
    }

    private GameObject m_mainLv;
    public GameObject mainLv
    {
        get
        {
            if (m_mainLv == null)
            {
                m_mainLv = new GameObject(DisplayLevel.mainview.ToString());
                InitDisplayLvObj(DisplayLevel.mainview, m_mainLv);
            }
            return m_mainLv;
        }
    }

    private GameObject m_joyStickLv;
    public GameObject joyStickLv
    {
        get
        {
            if (m_joyStickLv == null)
            {
                m_joyStickLv = new GameObject(DisplayLevel.joystick.ToString());
                InitDisplayLvObj(DisplayLevel.joystick, m_joyStickLv);
            }
            return m_joyStickLv;
        }
    }

    private GameObject m_confirmLv;
    public GameObject confirmLv
    {
        get
        {
            if (m_confirmLv == null)
            {
                m_confirmLv = new GameObject(DisplayLevel.confirm.ToString());
                InitDisplayLvObj(DisplayLevel.confirm, m_confirmLv);
            }
            return m_confirmLv;
        }
    }

    private GameObject m_loadingLv;
    public GameObject loadingLv
    {
        get
        {
            if (m_loadingLv == null)
            {
                m_loadingLv = new GameObject(DisplayLevel.loading.ToString());
                InitDisplayLvObj(DisplayLevel.loading, m_loadingLv);
            }
            return m_loadingLv;
        }
    }

    private GameObject m_tipsLv;
    public GameObject tipsLv
    {
        get
        {
            if (m_tipsLv == null)
            {
                m_tipsLv = new GameObject(DisplayLevel.tips.ToString());
                InitDisplayLvObj(DisplayLevel.tips, m_tipsLv);
            }
            return m_tipsLv;
        }
    }

    public GameObject GetDisplayLv(DisplayLevel lv) {
        switch (lv) { 
            case DisplayLevel.mainview:
                return mainLv;
            case DisplayLevel.joystick:
                return joyStickLv;
            case DisplayLevel.confirm:
                return confirmLv;
            case DisplayLevel.loading:
                return loadingLv;
            case DisplayLevel.tips:
                return tipsLv;
            default:
                return mainCanvas;
        }
    }

    public void InitDisplayLvObj(DisplayLevel lv,GameObject lvObj) {
        lvObj.layer = LayerMask.NameToLayer("UI");
        lvObj.transform.SetParent(mainCanvas.transform);
        RectTransform rt= lvObj.AddComponent<RectTransform>();
        rt.anchoredPosition = UI_PIVOT_CENTER;
        rt.anchorMin = Vector2.zero;
        rt.anchorMax = Vector2.one;
        rt.localEulerAngles = Vector3.zero;
        rt.localPosition = Vector3.zero;
        rt.localScale = Vector3.one;
        //rt.offsetMax = Vector2.zero;
        //rt.offsetMin = Vector2.zero;
        rt.sizeDelta = Vector2.zero;
        //Convert.ToInt32(lv);
        uiHierarchyLists.Add(lv.GetHashCode(), lvObj);
        foreach (int key in uiHierarchyLists.Keys)
        {
            uiHierarchyLists[key].transform.SetSiblingIndex(key);
        }
        
        //Canvas cv = lvObj.AddComponent<Canvas>();
        //cv.overridePixelPerfect = true;
        //cv.pixelPerfect = false;
        //cv.overrideSorting = true;
        //cv.sortingOrder = displayLevelSortOrder[lv];
        ////可能需要把父canvas的GraphicRaycaster移除掉，否则会阻挡其他canvas的点击
        //GraphicRaycaster gr = lvObj.AddComponent<GraphicRaycaster>();
    }

    void Start() {
        displayLevelSortOrder[DisplayLevel.none] = 0;
        displayLevelSortOrder[DisplayLevel.mainview] = 0;
        displayLevelSortOrder[DisplayLevel.joystick] = 10;
        displayLevelSortOrder[DisplayLevel.confirm] = 20;
        displayLevelSortOrder[DisplayLevel.loading] = 30;
        displayLevelSortOrder[DisplayLevel.tips] = 40;
        uiCamera = GameObject.Find("UICamera").GetComponent<Camera>();
    }

    /// <summary>
    /// 创建面板-没有创建时参数需要传递
    /// </summary>
    [Obsolete]
    public void CreatePanel(string abName,string assetName,Type objType,DisplayLevel displayLv=DisplayLevel.mainview,DestroyType destroyType=DestroyType.IMMEDIATE_DESTROY) 
    {
        //if (this.GetUIComponent(AssemblePanelName(abName, assetName)) != null) {
            
        //}
        //else {
        //    Dictionary<string, object> paramDic = new Dictionary<string, object>();
        //    paramDic.Add(Param_AssetBundleName, abName);
        //    paramDic.Add(Param_AssetName, assetName);
        //    paramDic.Add(Param_DisplayLv, displayLv);
        //    paramDic.Add(Param_DestroyType, destroyType);
        //    MainFacade.Instance.ResourceMgr.LoadAsset(abName, assetName, objType, paramDic, LoadPanelCompleted);
        //}
    }

    [Obsolete]
    public void CreatePanel(Dictionary<string,object> paramDic, Type objType, Action<UnityEngine.Object> mediatorCallBack)
    {
        MainFacade.Instance.ResourceMgr.LoadAsset(paramDic[Param_AssetBundleName].ToString(), paramDic[Param_AssetName].ToString(), objType, paramDic, LoadPanelCompleted);
    }

    /// <summary>
    /// 创建面板-有创建时参数需要传递
    /// </summary>
    /// <param name="paramDic"></param>
    /// <param name="objType"></param>
    /// <param name="mediatorCallBack"></param>
    public void CreatePanel(string abName, string assetName, Type objType, Action<UnityEngine.Object, Dictionary<string, object>> mediatorCallBack, Dictionary<string, object> paramDic =null, DisplayLevel displayLv = DisplayLevel.mainview, DestroyType destroyType = DestroyType.IMMEDIATE_DESTROY)
    {
        MainFacade.Instance.ResourceMgr.LoadAsset(abName, assetName, objType, paramDic, mediatorCallBack);
    }

    /// <summary>
    /// 初始化ui对象并缓存,供加载资源成功后，mediator里面初始化view对象后调用。应该要缓存view脚本对象的，后续将UIManager改造移到热更脚本里去再调整
    /// </summary>
    /// <param name="go"></param>
    /// <param name="paramDic"></param>
    public void LoadPanelCompleted(UnityEngine.Object go,Dictionary<string,object> paramDic)
    {
        //后续uimanager移到热更脚本里后，这里面paramDic的参数key替换成UIDefine里的定义

        string abName = paramDic["abName"].ToString();
        string assetName = paramDic["assetName"].ToString();
        if (GetUIComponent(AssemblePanelName(abName, assetName).ToLower())!=null) {//短暂瞬间发送了多个面板创建请求，不用再添加新面板了，直接回调
           
            return;
        }
        GameObject viewCom= GameObject.Instantiate(go) as GameObject;
        viewCom.SetActive(false);
        MainUtil.Log("加载视图成功>>>>>>>>>>>>>>>>>>>>>:" + viewCom.name);
        
        uiLists.Add(AssemblePanelName(abName,assetName),new UIGameObject(viewCom,abName,assetName));

        viewCom.name = assetName;
        DisplayLevel dl =(DisplayLevel) Enum.Parse(typeof(DisplayLevel),paramDic["DisplayLevel"].ToString());
        viewCom.transform.parent = GetDisplayLv(dl).transform;
        RectTransform vcRt= viewCom.transform.GetComponent<RectTransform>();
        vcRt.anchoredPosition = UI_PIVOT_CENTER;
        vcRt.anchorMin = Vector2.zero;
        vcRt.anchorMax = Vector2.one;
        vcRt.localEulerAngles = Vector3.zero;
        vcRt.localPosition = Vector3.zero;
        vcRt.localScale = Vector3.one;
        //相对父对象的偏移
        vcRt.offsetMax = Vector2.zero;
        vcRt.offsetMin = Vector2.zero;
    }

    public void LoadPanelCompleted(UnityEngine.Object go, Dictionary<string, object> paramDic, Action<UnityEngine.Object, Dictionary<string, object>> mediatorCallBack)
    {
        LoadPanelCompleted(go, paramDic);

        if(mediatorCallBack != null)
        {
            mediatorCallBack(go, paramDic);
        }
    }


    public string AssemblePanelName(string abName,string assetName) {
        return string.Format("{0}_{1}", abName, assetName).ToLower();
    }

    /// <summary>
    /// 标记立即销毁或延迟销毁的 从uiLists移除
    /// </summary>
    /// <param name="obj"></param>
    public void DestroyUI(GameObject obj) {
        string toRemove = null;
        foreach (string name in uiLists.Keys) {
            if (uiLists[name].obj == obj) {
                uiLists[name].Dispose();
                toRemove = name;
                break;
            }
        }
        if (toRemove != null) {
            uiLists.Remove(toRemove);
        }
    }

    public GameObject GetUIComponent(string name) {
        if (uiLists.ContainsKey(name))
        {
            return uiLists[name].obj;
        }
        else {
            return null;
        }
    }

    //---------------------设置图片
    public void SetImage(string abName,string assetName,Image img) {
        MainFacade.Instance.ResourceMgr.LoadAsset(abName, assetName, typeof(UnityEngine.Texture2D), null, (UnityEngine.Object asset, Dictionary<string, object> paramList) =>{
            Texture2D texture = asset as Texture2D;
            Sprite sp = Sprite.Create(texture, new Rect(0,0, texture.width, texture.height), Vector2.one*0.5f);
            //可能可以显示名字
            sp.name = asset.name;
            img.sprite = sp;
        });
    }
}
